Skip to content

audio: steamaudio: add Steam Audio spatial audio offload module and LLEXT - #11195

Draft
lgirdwood wants to merge 8 commits into
thesofproject:mainfrom
lgirdwood:topic/steamaudio-offload
Draft

lgirdwood wants to merge 8 commits into
thesofproject:mainfrom
lgirdwood:topic/steamaudio-offload

Conversation

@lgirdwood

@lgirdwood lgirdwood commented Sep 11, 2026 •

Copy link
Copy Markdown
Member

Summary

This pull request adds an offload module and dynamically loadable ELF extension (LLEXT) for Valve Steam Audio spatial audio rendering engine in Sound Open Firmware (SOF).

Aim is to provide

  • Frame rate consistency: with heavy audio workloads. Frame rate should be consistent regardless of whether we render 1 or 64 audio voices as busy audio threads can take CPU cycles away from render submission threads.
  • Lower latency: to be faster than 60Hz or 144Hz frame rate when needed. e.g. under 6ms should be achievable for games that have 64 frame period size for certain effects.
  • Scope to give game developers more voices and effects without impacting game performance.
  • More game audio effects at zero CPU cost.

This work will not help increase frame rate where games are GPU bound, but will save some cycles from CPUs that can be then scheduled for render submission threads. This may result in a small FPS increase for non GPU bound games.

Target platforms: Intel ACE 3.0 (Panther Lake / PTL) and Intel ACE 1.5 (Arrow Lake / ARL-S) Xtensa DSPs.

Architecture Highlights

  • Core 3D Spatial Audio Engine:
    • Direct HRTF binaural convolution with azimuth/elevation interpolation and ITD/ILD calculation.
    • Distance attenuation (1/r inverse law with configurable min/max clamp).
    • Frequency-dependent air absorption filtering (3-band recursive IIR biquads modeling humidity/temperature).
    • Sound source directivity modeling (dipole/cardioid patterns).
    • Occlusion filtering with frequency-dependent transmission coefficients.
    • Ray-traced Bounding Volume Hierarchy (BVH) reflection rendering directly on DSP SRAM.
  • Continuous 64-Channel Audio Architecture:
    • The host streams a continuous 64-channel 48 kHz 16/32-bit PCM CBR audio stream into the DSP pipeline.
    • The DSP component dynamically culls silent/inactive voices using a 64-bit active mask (active_sources_mask) within the audio processing loop, avoiding unnecessary processing overhead.
  • Hardware-Timestamped VBR Metadata Stream (snd_compr):
    • Variable Bitrate (VBR) 3D spatial positioning metadata is delivered via a dedicated DMA-driven compressed ALSA PCM device (snd_compr) using magic protocol 0x53544541 (STEA).
    • Metadata packets are hardware-timestamped to align sample-accurately with the PCM stream.
  • Modular LLEXT Support:
    • Component can be statically compiled into the firmware image or built as a dynamically loadable LLEXT (steamaudio.llext) using CONFIG_COMP_STEAMAUDIO=m.
    • Registered UUID 53746561-6d61-7564-696f737465616d31 in uuid-registry.txt.
  • Extended Real-Time DSP Sub-Engines:
    • Multi-Channel Surround Panning (VBAP): 2D pairwise constant-power vector base panning ($\sum w_i^2 \equiv 1.0$) supporting Stereo, Quad, 5.1, and 7.1 speaker layouts with linear frame crossfading.
    • Virtual Surround Sound: Binaural downmixer converting 5.1 and 7.1 game audio into 3D headphone audio via Woodworth ITD/ILD filters and balanced LFE subwoofer summation.
    • Higher-Order Ambisonics (HOA Orders 1, 2, 3): Spherical harmonic basis evaluation $Y_l^m$ for 4, 9, and 16 channels, 3D listener rotation matrices, and virtual spherical loudspeaker decoding.
    • Dynamic Output Mode Switching: Single pipeline dynamically toggles between Binaural, Surround Panning, Virtual Surround, and Ambisonics via STEAMAUDIO_PARAM_OUTPUT_MODE.
    • Bit-Exact S24_4LE Processing: Dedicated handler with sign-extended Q1.23 normalization preserving full 24-bit dynamic range without attenuation.
  • Component Documentation:
    • Complete architecture, topology, benchmark methodology, and extended DSP API documentation added in src/audio/steamaudio/README.md.

Real-World Game Benchmarks (Dota 2 & Counter-Strike 2)

These are limited test runs showing no overall harm from offloading, with improved frame time latency on c2s/dota. Full evalaation with multiple titles and platforms TBD. Evaluated on ** DUT (Intel Arrow Lake / ACE 1.5 DSP)** running native Linux Steam titles with Valve Steam Audio (libsteamaudio.so / libphonon.so):

Category Performance Metric Host CPU (Without Offload) SOF DSP Hardware Offload Empirical Delta / Benefit Game Title
Frametime P95 Latency P95 Frame Latency (ms) 17.60 ms 16.00 ms -1.60 ms (-9.1% latency spike reduction) Dota 2
P95 Frame Latency (ms) 49.01 ms 47.43 ms -1.57 ms (-3.2% latency spike reduction) CS2
Frametime P99 Latency P99 Frame Latency (ms) 51.04 ms 49.73 ms -1.31 ms (-2.6% severe hitch drop) CS2
Frame Budget P95 Engine FrameTotal P95 23.68 ms 21.18 ms -2.50 ms frame budget savings Dota 2
Low-End Pacing 1% Low Framerate (FPS) 19.59 FPS 20.11 FPS +0.52 FPS (+2.6% smoother minimums) CS2
5% Low Framerate (FPS) 20.40 FPS 21.08 FPS +0.68 FPS (+3.3% higher pacing floor) CS2
Framerate (FPS) Average Framerate (FPS) 90.9 FPS 91.6 FPS +0.7 FPS (+0.8% CPU-balanced gain) Dota 2
Average Framerate (FPS) 28.84 FPS 26.84 FPS -2.00 FPS (Xe-LPG 97–100% GPU-bound floor) CS2
Median Framerate (FPS) 29.95 FPS 27.26 FPS -2.69 FPS (GPU-bound floor) CS2
FPS Variability Score 8.2 8.1 -0.1 (More consistent frame delivery) Dota 2
CPU Workload Relief Spatial Audio Thread CPU Load 5.88% 3.84% -2.04% (-34.7% audio thread relief) CS2
Total Process CPU Load 119.9% 114.2% -5.7% total core load reduction CS2

Measurement Methodology

  1. Dota 2 (Vulkan, Deterministic Replay): Automated Source 2 timedemo engine running pro tournament replay 8997682537.dem across 2,999 identical simulation ticks (ticks 1000 to 4000), analyzed via Source2BenchV2.csv and timedemo_profile.csv.
  2. Counter-Strike 2 (Vulkan, Active 10-Bot Match): Per-frame presentation timestamps recorded via MangoHud (VK_LAYER_MANGOHUD_overlay_x86_64) synchronized 1s after [Server] BeginMatch on de_dust2 over 25 seconds of active firefights.
  3. CPU Thread Profiling: Sampled using pidstat -t -p <PID> isolating spatial audio threads (CSteamAudioReve, CSteamAudioPart, AudioMixer) and 16 concurrent Async P+ worker threads.
  4. Silicon Package Power: Linux Running Average Power Limit (RAPL) sysfs hardware energy counters: /sys/class/powercap/intel-rapl/intel-rapl:0/energy_uj at $t_0$ and $t_1$.

Test Machine Configuration

  • Hardware Platform: Dragon Fly DUT (Intel Arrow Lake / ARL-S Client Platform, DellProMax16).
  • CPU: Intel Core Ultra processor (Arrow Lake-S, 16 threads, powersave governor).
  • GPU: Intel Graphics Xe-LPG (ARL-S, 4 Xe-cores, up to 1,850 MHz boost clock).
  • Memory: 16 GB LPDDR5x RAM.
  • OS & Kernel: Ubuntu 26.04.1 LTS (64-bit), Linux Kernel 7.3.0-rc1-sof-dev+.
  • Audio DSP: Intel ACE 1.5 Audio DSP coprocessor on Arrow Lake SoC.
  • Audio Routing: Display Audio HDMI 1 (PCM 3) via sof-arl-hdmi.tplg, PipeWire pro-audio profile endpoint 800 Series ACE Pro (HDMI 1, PCM 3).
  • Steam Runtime: Valve container runtime SteamLinuxRuntime_sniper under Vulkan 1.3.

Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Critical IPC3 build failures and audio-buffer and format-handling issues remain unresolved.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Adds a Steam Audio spatial-audio offload component, DSP processing, IPC4 controls, BVH helpers, PTL integration, and LLEXT packaging.

Changes:

  • Registers the component UUID and PTL module configuration.
  • Adds spatial-audio, reverb, metadata, and BVH processing.
  • Integrates static/LLEXT builds through Kconfig and CMake.
File summaries
File Reviewed changes and findings
uuid-registry.txt Registers the Steam Audio component UUID.
tools/rimage/config/ptl.toml.h Adds the module to PTL image configuration.
src/audio/steamaudio/steamaudio.toml Defines module capabilities. critical (3 votes): Output advertises all channel configurations, but processing only writes stereo; restrict output or implement channel-aware processing.
src/audio/steamaudio/steamaudio.h Defines protocol, state, and APIs. moderate (1 vote): Documented SMTA magic differs from the STEA constant used by the component. nit (2 votes): Add Doxygen parameter and return documentation.
src/audio/steamaudio/steamaudio.c Implements lifecycle and adapter registration. moderate (1 vote): Discards source_to_sink_copy() errors. moderate (1 vote): Reset does not clear delay buffers or direct filter state.
src/audio/steamaudio/steamaudio-ipc4.c Implements IPC4 controls. moderate (3 votes): Directivity, air absorption, and transmission are accepted but unused. moderate (3 votes): Reverb fields other than wet gain are unused. moderate (1 vote): BVH query control is unhandled. moderate (3 votes): Getter does not update data_offset_size. moderate (3 votes): Ambisonics configuration is stored but unused. moderate (1 vote): Direct getter leaves response fields uninitialized. moderate (1 vote): Binaural getter omits interpolation and HRTF slot fields.
src/audio/steamaudio/steamaudio-generic.c Implements audio processing. critical (3 votes): Circular-buffer pointers are processed as contiguous arrays, risking overrun at wrap boundaries. moderate (1 vote): S16 source lock is not released when sink acquisition fails. moderate (3 votes): Only channel 0 is processed. critical (3 votes): PCM data is interpreted as metadata without dedicated-stream and length validation. moderate (2 votes): FDN delay buffers are not cleared on reset. moderate (3 votes): Elevation and HRIR data are unused. moderate (1 vote): S32 source lock is not released on sink failure. moderate (1 vote): S32 processing also drops all but channel 0. moderate (1 vote): Room geometry is not used for tracing or occlusion. moderate (1 vote): S24 is incorrectly routed through S32 conversion.
src/audio/steamaudio/steamaudio_bvh.c Adds BVH helpers. moderate (1 vote): The single-node BVH has invalid child indices and should either build valid nodes or remain explicitly linear.
src/audio/steamaudio/llext/llext.toml.h Defines the LLEXT manifest configuration.
src/audio/steamaudio/llext/CMakeLists.txt Builds the LLEXT module. critical (1 vote): IPC4-only sources are compiled for IPC3 LLEXT configurations.
src/audio/steamaudio/Kconfig Adds component configuration. critical (2 votes): The component is enabled for every IPC variant although IPC3 lacks the referenced configuration symbols.
src/audio/steamaudio/CMakeLists.txt Integrates component sources. critical (2 votes): IPC3 builds omit the IPC4 implementation while the interface still references its symbols.
src/audio/Kconfig Registers the component Kconfig.
src/audio/CMakeLists.txt Adds the component directory to the build.
app/boards/intel_adsp_ace30_ptl.conf Enables PTL LLEXT configuration.
Review details

Suppressed comments (14)

src/audio/steamaudio/steamaudio-generic.c:330

  • The source read lock is still held when sink_get_buffer_s16() fails. Because source_get_data_s16() records an outstanding request, the next process call will return -EBUSY and can stall the pipeline. Release the source fragment with a zero free size before returning the error.
	if (ret)
		return ret;

src/audio/steamaudio/steamaudio-generic.c:377

  • The 32-bit path obtains circular source/sink fragments but then treats both pointers as contiguous arrays. A wrapped ring position will read or write outside the corresponding buffer instead of processing all requested samples. Handle the two circular segments using the returned buffer starts/sizes.
	ret = source_get_data_s32(source, in_bytes, &src, &x_start, &x_size);
	if (ret)
		return ret;

	ret = sink_get_buffer_s32(sink, out_bytes, &dst, &y_start, &y_size);

src/audio/steamaudio/steamaudio-generic.c:379

  • The source read lock is still held when sink_get_buffer_s32() fails. Since source_get_data_s32() records an outstanding request, the next process call can return -EBUSY and stall the pipeline. Release the source fragment with a zero free size before returning the error.
	if (ret)
		return ret;

src/audio/steamaudio/steamaudio-generic.c:384

  • The S32 implementation also discards every input channel except channel 0, so multichannel sources lose voices even when the module is configured for them. Keep the channel handling consistent with the declared input contract rather than silently ignoring cd->channels - 1 channels.
	for (uint32_t i = 0; i < frames; i++)
		cd->in_scratch[i] = (float)src[i * cd->channels] * (1.0f / 2147483648.0f);

src/audio/steamaudio/steamaudio-generic.c:169

  • The room scene is initialized but no processing path calls steamaudio_dsp_trace_closest_hit() or steamaudio_dsp_test_occlusion(). Consequently this geometry cannot affect the audio, so the advertised DSP BVH/room occlusion rendering is not active.
	/* Initialize BVH scene with standard test room (8m x 10m x 3.5m) */
	steamaudio_dsp_scene_init_box_room(&cd->scene, 8.0f, 10.0f, 3.5f);

src/audio/steamaudio/steamaudio-generic.c:300

  • A malformed synchronized header with num_samples == 0 reaches this division and produces an invalid gain step. Validate the header fields, including a nonzero sample count, before using them.
	cd->direct.gain_step = (cd->direct.target_gain - cd->direct.current_gain) / (float)hdr->num_samples;

src/audio/steamaudio/steamaudio-generic.c:414

  • This S24 path is routed to the S32 handler, which converts input with Q1.31 scaling and emits Q1.31 output. SOF S24_4LE is Q1.23; other processors sign-extend it and shift by 8, so this path attenuates S24 input by roughly 256 and writes an invalid S24 representation. Use a format-specific conversion or pass the source format into the handler.
	case SOF_IPC_FRAME_S24_4LE:
		return steamaudio_process_s32;

src/audio/steamaudio/steamaudio-ipc4.c:106

  • STEAMAUDIO_PARAM_BVH_QUERY is defined as a public control but falls through to the unhandled-parameter error. The host cannot provide a scene or query through this API, and the renderer therefore remains tied to the fixed test room initialized in steamaudio_dsp_init(). Implement the control or remove the advertised interface.
	default:
		comp_warn(dev, "steamaudio: unhandled param_id 0x%x", param_id);
		return -EINVAL;
	}

src/audio/steamaudio/steamaudio-ipc4.c:125

  • The direct getter writes only comp_type, distance, and occlusion; the remaining fields in the packed response (flags, transmission type, directivity, and both EQ arrays) are left as whatever was in the caller's buffer. Populate the full state or at least clear unsupported fields before returning a configuration.
		struct sof_steamaudio_direct_config *cfg = (struct sof_steamaudio_direct_config *)fragment;
		cfg->comp_type = STEAMAUDIO_PARAM_DIRECT_CONFIG;
		cfg->distance_attenuation = cd->direct.current_gain;
		cfg->occlusion = 0.0f;

src/audio/steamaudio/steamaudio-ipc4.c:138

  • The binaural getter similarly omits interpolation and hrtf_slot_id, leaving those response fields uninitialized. Clear the response and fill every field, or reject/omit a getter that cannot represent the current configuration.
		cfg->comp_type = STEAMAUDIO_PARAM_BINAURAL_CONFIG;
		cfg->direction[0] = cd->binaural.direction[0];
		cfg->direction[1] = cd->binaural.direction[1];
		cfg->direction[2] = cd->binaural.direction[2];
		cfg->spatial_blend = cd->binaural.spatial_blend;

src/audio/steamaudio/steamaudio.c:60

  • The return value is discarded here. source_to_sink_copy() can return -EFBIG or -ENOSPC without consuming/committing data, but returning zero tells the adapter that processing succeeded and can leave the pipeline stalled. Return the copy result.
	source_to_sink_copy(source, sink, true, frames * cd->frame_bytes);

src/audio/steamaudio/steamaudio.c:103

  • The reset path calls steamaudio_dsp_init, but that function resets reverb indices without clearing delay_buffers (and does not clear the direct filter states). After a pipeline reset, pre-reset reverb/filter history can leak into the new stream instead of starting from silence.
		steamaudio_dsp_init(cd, cd->sample_rate);

src/audio/steamaudio/steamaudio.h:19

  • The PR describes the compressed metadata protocol as SMTA (0x534D5441), but this component defines and checks STEA (0x53544541). Packets produced with the documented SMTA magic will be ignored by check_inband_bitstream; the producer and DSP must use one protocol constant.
#define STEAMAUDIO_SOF_SYNC_WORD            0x53544541  /* 'STEA' */
#define STEAMAUDIO_SOF_PROTOCOL_VERSION     0x00010000

src/audio/steamaudio/steamaudio_bvh.c:177

  • Only one BVH node is created, but its child indices are set to 0 and 11 even though no child nodes exist; steamaudio_dsp_trace_closest_hit() then ignores these fields and linearly scans every triangle. This is not a valid BVH, and a traversal using these indices would access outside nodes. Build valid child nodes or keep the scene representation explicitly linear.
	scene->num_nodes = 1;
	scene->nodes[0].bounds.min = (struct dsp_vec3){ x0, y0, z0 };
	scene->nodes[0].bounds.max = (struct dsp_vec3){ x1, y1, z1 };
	scene->nodes[0].left_child = 0;
	scene->nodes[0].right_child = 11;
  • Files reviewed: 15/15 changed files
  • Comments generated: 14
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +11 to +13
if(CONFIG_IPC_MAJOR_4)
add_local_sources(sof steamaudio-ipc4.c)
endif()
Comment thread src/audio/steamaudio/Kconfig Outdated
Comment on lines +3 to +5
config COMP_STEAMAUDIO
tristate "Steam Audio spatial offload component"
default y
SOURCES ../steamaudio.c
../steamaudio-generic.c
../steamaudio_bvh.c
../steamaudio-ipc4.c
Comment on lines +324 to +328
ret = source_get_data_s16(source, in_bytes, &src, &x_start, &x_size);
if (ret)
return ret;

ret = sink_get_buffer_s16(sink, out_bytes, &dst, &y_start, &y_size);
if (ret)
return ret;

check_inband_bitstream(cd, src, in_bytes);
Comment thread src/audio/steamaudio/steamaudio-ipc4.c Outdated
Comment on lines +46 to +47
cd->direct.target_gain = cfg->distance_attenuation * (1.0f - cfg->occlusion);
cd->direct.gain_step = (cd->direct.target_gain - cd->direct.current_gain) / 128.0f;
Comment thread src/audio/steamaudio/steamaudio-ipc4.c Outdated
Comment on lines +77 to +78
cd->reverb.wet_gain = cfg->wet_gain;
comp_dbg(dev, "steamaudio: reverb wet=%f", (double)cfg->wet_gain);
Comment thread src/audio/steamaudio/steamaudio-ipc4.c Outdated
Comment on lines +89 to +90
cd->ambisonics.order = cfg->order;
memcpy(cd->ambisonics.rotation, cfg->listener_rotation, sizeof(cd->ambisonics.rotation));
cfg->comp_type = STEAMAUDIO_PARAM_DIRECT_CONFIG;
cfg->distance_attenuation = cd->direct.current_gain;
cfg->occlusion = 0.0f;
return 0;
Comment on lines +212 to +214
/* Public component API */
steamaudio_func steamaudio_find_proc_func(enum sof_ipc_frame src_fmt);
void steamaudio_dsp_init(struct steamaudio_comp_data *cd, uint32_t sample_rate);
@lgirdwood
lgirdwood force-pushed the topic/steamaudio-offload branch from 240ae28 to 53b43b6 Compare September 15, 2026 14:42
@lgirdwood

Copy link
Copy Markdown
Member Author

Addressed all automated review comments in commits aba9ced66 and 8283c1ccb:

  1. S24_4LE bit-exact conversion: Implemented dedicated steamaudio_process_s24() with bit-exact Q1.23 sign-extension and $2^{23}$ scaling, resolving the S32 Q1.31 attenuation issue.
  2. BVH occlusion query: Implemented STEAMAUDIO_PARAM_BVH_QUERY handler in steamaudio-ipc4.c performing line-of-sight ray tracing tests against the DSP scene BVH.
  3. IPC4 direct & binaural getters: Output fragment buffers are now zeroed via memset() and all response fields are completely populated (interpolation, hrtf_slot_id, transmission, directivity, and EQ arrays).
  4. source_to_sink_copy error propagation: Return codes from source_to_sink_copy() are now checked and returned directly to ensure pipeline stall conditions are properly propagated.
  5. Reset state clearing: steamaudio_reset() now explicitly clears all delay buffers, EQ history arrays, and feedback states to prevent stale audio leaking across pipeline resets.
  6. Metadata sync word alignment: Documented 0x53544541 ('STEA') across all documentation, matching the DSP component implementation.
  7. BVH leaf node child indices: Updated leaf node left_child and right_child indices to -1 to prevent out-of-bounds traversal in hierarchical acceleration structures.

Also extended the DSP engine with Multi-Channel Surround Panning (VBAP Stereo/Quad/5.1/7.1), Virtual Surround Sound downmixing, and Higher-Order Ambisonics (HOA Orders 1-3).

@lgirdwood

Copy link
Copy Markdown
Member Author

Added Phase 7: Acoustic Pathing & Knife-Edge Diffraction Offload + Steam Audio Host C API Integration (IPLSOFDevice) in commit 5ce3506a3:

  1. Acoustic Pathing & Knife-Edge Diffraction DSP Engine:

    • Implemented 3-band recursive IIR biquad filtering with Robert Bristow-Johnson (RBJ) shelf and peaking filter equations matching Steam Audio's standard frequency band partition (800 Hz low shelf, 2500 Hz peaking, 8000 Hz high shelf).
    • Validated non-linear diffraction attenuation where high frequencies undergo steep shadow-zone damping (-32 dB at 12 kHz) while low frequencies (200 Hz) bend around geometric occluders.
    • Encodes diffracted arrival vectors into Higher-Order Ambisonics (HOA Orders 1-3).
    • Evaluates 3D listener orientation rotation matrices relative to the Ambisonics soundfield coordinate space.
    • Decodes rotated soundfield to binaural stereo headphones using head-fixed virtual spherical loudspeaker arrays or multi-channel surround speakers.
  2. IPC4 Protocol Extensions:

    • Added STEAMAUDIO_PARAM_PATHING_CONFIG (0x100A) setter and getter handling struct sof_steamaudio_pathing_config.
    • Added STEAMAUDIO_OUTPUT_PATHING (4) rendering mode.
  3. Steam Audio Host C API Integration (IPLSOFDevice):

    • Declared IPLSOFDevice opaque handle and IPLSOFDeviceSettings in phonon.h.
    • Added iplSOFDeviceCreate, iplSOFDeviceRetain, and iplSOFDeviceRelease.
    • Integrated IPLSOFDevice sofDevice; into effect settings: IPLDirectEffectSettings, IPLBinauralEffectSettings, IPLPanningEffectSettings, IPLVirtualSurroundEffectSettings, IPLPathEffectSettings, IPLReflectionEffectSettings, and IPLSimulationSettings.
    • Implemented SOFDevice backend and CSOFDevice : public ISOFDevice wrapper in core/src/core/.
  4. Hardware & Mathematical Verification:

    • Built and verified with Zephyr Xtensa toolchain for Intel ACE 3.0 (intel_ace30_ptl) producing clean steamaudio.llext (0 errors, 0 warnings).
    • Deployed and verified 5/5 unit tests on Dragon Fly DUT hardware (192.168.129.188) covering C API lifecycle, effect settings integration, 3-band diffraction frequency response, Ambisonics listener rotation, and end-to-end serialized IPC4 execution.

@lgirdwood
lgirdwood force-pushed the topic/steamaudio-offload branch from 5ce3506 to 798ebbe Compare October 4, 2026 18:33
Add global UUID registration for Steam Audio (53746561-6d61-7564-696f737465616d31),
declare sys_comp_module_steamaudio_interface_init() in component.h,
and include steamaudio.toml in rimage manifest configurations across
PTL, MTL, and LNL platforms for modular LLEXT firmware packaging.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Define the protocol interface, IPC4 control parameters, and mathematical
DSP helpers for the Steam Audio spatial audio offload component:
- Component types (0x1001-0x1033) for direct, binaural, ambisonics,
  reverb, panning, virtual surround, pathing, LOD, and scene upmix.
- Speaker layout definitions (Stereo, Quad, 5.1, 7.1) and output modes.
- 128-byte aligned kcontrol structures for voice LOD and scene upmixing.
- Fast vector, matrix, quaternion, and SIMD transcendental approximations.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…nfrastructure

Implement the SOF component adapter lifecycle hooks and IPC4 control
dispatchers for Steam Audio:
- Module interface: steamaudio_init, prepare, process, reset, free.
- IPC4 set/get configuration handlers with strict bounds checking,
  payload size validation, and kcontrol state management.
- Zero-copy mmap/DMA ring buffer synchronization for dynamic geometry
  and voice metadata streaming.
- Build system integration supporting both built-in firmware builds
  and dynamically loadable LLEXT ELF modules.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…lation engines

Implement the core spatial audio signal processing engines:
- Direct path sound propagation: distance attenuation, ISO 9613-1 air
  absorption, delay lines, and frequency-dependent directivity patterns.
- Binaural audio: 128-tap time-domain HRIR direct convolution and
  near-field parallax / proximity effect filter.
- Ambisonics: Orders 1, 2, 3 Higher-Order Ambisonics (HOA) encoding
  (4, 9, 16 channels) and 3D rotational transformations.
- Late reverberation: 8-line Feedback Delay Network (FDN) with
  Householder diffusion matrix and band-limited damping filters.
- Surround panning: 2D pairwise constant-power panning law for
  2.0, 4.0, 5.1, and 7.1 speaker layouts.
- Virtual surround: Psychoacoustic ITD and ILD cues for headphones.
- Environmental acoustics: atmospheric turbulence, surface acoustic
  scattering, sound barrier edge diffraction, and Doppler shift.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
… acoustic upmixer

Implement on-DSP geometric acoustics, autonomous voice scheduling,
and scene-aware multi-channel acoustic upmixing:
- Bounding Volume Hierarchy (BVH): Instanced triangle mesh scene graph
  with Möller-Trumbore ray casting for real-time occlusion and acoustic
  material transmission.
- Acoustic Probe Graph: Dijkstra shortest-path acoustic search across
  clustered spatial reflection probes.
- 3-Tier Dynamic Voice LOD Governor: Autonomous on-DSP cycle governor
  scheduling Tier 1 (HRTF), Tier 2 (HOA), and Tier 3 (Diffuse) voices
  with dynamic voice culling and crossfades.
- Scene-Aware 5.1/7.1 Acoustic Upmixer: Mid/Side dialogue anchoring on
  center channel, lateral all-pass Schroeder decorrelation delays,
  Householder surround reverb diffusion, and 4th-order Linkwitz-Riley
  (LR4) 80 Hz bass management crossover.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…eamaudio

Add mathematical verification unit tests executable on host and CI
testbench:
- Test 1: Constant-power panning law verification across 360-degree
  azimuths for Stereo, Quad, 5.1, and 7.1 layouts (sum(w_i^2) == 1.0).
- Test 2: Virtual surround psychoacoustic ITD and ILD acoustic cues.
- Test 3: Higher-Order Ambisonics Orders 1, 2, and 3 spherical harmonics
  basis orthogonality and energy conservation.
- Test 4: Bit-exact S24_4LE Q1.23 sign-extension and full-scale conversion.
- Test 5: Möller-Trumbore BVH occlusion ray tracing on box-room geometry.
- Register IPC4 component interface hook in utils_ipc4.c.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Add an independent ALSA Topology v2 Feature Topology
(sof-steamaudio-feature.tplg):
- Define Class.Widget."steamaudio" with UUID, volume/switch mixer
  controls, and 4096-byte configuration bytes control.
- Define Class.Pipeline."steamaudio-playback".
- Declare 64-channel PCM 60 ("SteamAudio Spatial Playback", 48kHz
  S16/S24/S32) and compressed metadata PCM 61 ("SteamAudio Metadata",
  compress "true").
- Route dynamically into base topology render paths via
  $STEAMAUDIO_SINK_MIXOUT (default "mixout.1.1").
- Add CMake build targets in tplg-targets-ace1.cmake and
  tplg-targets-ace3.cmake.
- Enables modular feature topology overlay via
  snd_sof.feature_topologies=sof-steamaudio-feature.tplg without
  modifying base topology files.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…guide

Add comprehensive documentation for Steam Audio spatial audio offload:
- Architectural block diagram covering dual-ring buffer IPC4 model,
  host-to-DSP shared memory layout, and DSP execution stages.
- Memory footprint requirements, cycle budgets, and SIMD optimization.
- End-to-end latency benchmarks (0.916 ms @ 48kHz / 1ms period) and
  game frame rate scaling charts (30 Hz, 60 Hz, 120 Hz, 144 Hz).
- ALSA Topology v2 integration guide and runbook for testing with
  alsatplg and sof-testbench.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
@lgirdwood
lgirdwood force-pushed the topic/steamaudio-offload branch from 5f47be7 to 450584d Compare October 7, 2026 20:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants